package com.dingreading.cloud.admin.controller;

import com.alibaba.fastjson.JSONArray;
import com.dingreading.cloud.admin.dto.StoreContractDto;
import com.dingreading.cloud.admin.entity.StoreContract;
import com.dingreading.cloud.admin.entity.StoreContractFile;
import com.dingreading.cloud.admin.entity.StoreContractGift;
import com.dingreading.cloud.admin.entity.Stores;
import com.dingreading.cloud.admin.mapper.StoreContractMapper;
import com.dingreading.cloud.admin.service.*;
import com.dingreading.cloud.admin.util.AdminStaffRoleUtil;
import com.dingreading.cloud.admin.util.ContractFileUtil;
import com.dingreading.cloud.admin.util.StoreFollowEnum;
import com.dingreading.cloud.admin.util.StoreFollowUtil;
import com.dingreading.cloud.common.base.R;
import com.dingreading.cloud.common.util.*;
import com.mybatisflex.core.paginate.Page;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import io.swagger.annotations.ApiParam;
import org.apache.commons.collections4.CollectionUtils;
import org.apache.commons.lang3.StringUtils;
import org.springframework.cloud.context.config.annotation.RefreshScope;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.multipart.MultipartFile;

import javax.annotation.Resource;
import javax.servlet.ServletOutputStream;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;

@RefreshScope
@RestController
@RequestMapping("/system/storeContract")
@Api(tags = "总部-门店合同管理")
public class StoreContractController {

    @Resource
    private StoresService storesService;
    @Resource
    private StoreContractService storeContractService;
    @Resource
    private StoreContractFileService storeContractFileService;
    @Resource
    private StoreContractGiftService contractGiftService;
    @Resource
    private StoreContractMapper storeContractMapper;
    @Resource
    private AdminRoleStaffService adminRoleStaffService;


    @ApiOperation(value = "分页列表")
    @PostMapping(value = "/pageList")
    public R<Object> pageList(
            HttpServletRequest request,
            @ApiParam(value = "总部员工uid") @RequestParam(value = "headStaffUid") String headStaffUid,
            @ApiParam(value = "总部员工名") @RequestParam(value = "headStaffName") String headStaffName,
            @ApiParam(value = "分页公共类") PageUtil pageUtil,
            @ApiParam(value = "合同编号/销售姓名/门店名称/公司名称") @RequestParam(value = "keyword", required = false) String keyword,
            @ApiParam(value = "合同类型") @RequestParam(value = "contractType", required = false) Integer contractType,
            @ApiParam(value = "是否有保证金 0.无 1.有") @RequestParam(value = "deposit", required = false) Integer depositStatus,
            @ApiParam(value = "保证金是否已退 0.未退 1.已退") @RequestParam(value = "depositRefundStatus", required = false) Integer depositRefundStatus,
            @ApiParam(value = "合同到期开始日期") @RequestParam(value = "beginDate", required = false) String beginDate,
            @ApiParam(value = "合同到期结束日期") @RequestParam(value = "endDate", required = false) String endDate
    ) {
        Page<StoreContractDto> page = storeContractService.pageList(
                pageUtil, keyword, depositStatus, depositRefundStatus, contractType, beginDate, endDate
        );

        List<StoreContractDto> list = page.getRecords();
        if (CollectionUtils.isNotEmpty(list)) {
            List<Long> contractIds = list.stream().map(StoreContractDto::getId).collect(Collectors.toList());

            List<StoreContractFile> fileList = storeContractFileService.listByContractIdIn(contractIds);
            if (CollectionUtils.isNotEmpty(fileList)) {
                Map<Long, List<StoreContractFile>> map = fileList.stream()
                        .collect(Collectors.groupingBy(StoreContractFile::getContractId, Collectors.toList()));
                // 合同文件添加token
                String ipAddr = IpUtil.getIpAddr(request);
                String token = ContractFileUtil.getToken(ipAddr);
                for (StoreContractDto data : list) {
                    List<StoreContractFile> contractFiles = map.get(data.getId());
                    if (CollectionUtils.isNotEmpty(contractFiles)) {
                        contractFiles.forEach(file -> {
                            file.setUrl(file.getUrl() + token);
                        });
                        data.setFileList(contractFiles);
                    }
                }
            }
        }

        PageBeanDto data = new PageBeanDto();
        data.setTotal(page.getTotalRow());
        data.setList(list);
        return R.ok(data);
    }

    @ApiOperation(value = "按门店uid获取合同列表")
    @PostMapping(value = "/getList")
    public R<Object> getList(
            HttpServletRequest request,
            @ApiParam(value = "总部员工uid") @RequestParam(value = "headStaffUid") String headStaffUid,
            @ApiParam(value = "总部员工名") @RequestParam(value = "headStaffName") String headStaffName,
            @ApiParam(value = "门店uid") @RequestParam(value = "storeUid", required = false) String storeUid
    ) {
        List<StoreContract> list = storeContractService.listByStoreUid(storeUid);

        if (CollectionUtils.isNotEmpty(list)) {
            List<Long> contractIds = list.stream().map(StoreContract::getId).collect(Collectors.toList());

            List<StoreContractFile> fileList = storeContractFileService.listByContractIdIn(contractIds);
            if (CollectionUtils.isNotEmpty(fileList)) {
                Map<Long, List<StoreContractFile>> map = fileList.stream()
                        .collect(Collectors.groupingBy(StoreContractFile::getContractId, Collectors.toList()));
                // 合同文件添加token
                String ipAddr = IpUtil.getIpAddr(request);
                String token = ContractFileUtil.getToken(ipAddr);
                for (StoreContract contract : list) {
                    List<StoreContractFile> contractFiles = map.get(contract.getId());
                    if (CollectionUtils.isNotEmpty(contractFiles)) {
                        contractFiles.forEach(file -> {
                            file.setUrl(file.getUrl() + token);
                        });
                        contract.setFileList(contractFiles);
                    }
                }
            }

        }
        return R.ok(list);
    }

    @ApiOperation(value = "根据公司uid获取信息")
    @PostMapping(value = "/getBean", produces = "application/json; charset=UTF-8")
    public R<Object> getBean(
            HttpServletRequest request,
            @ApiParam(value = "总部员工uid") @RequestParam(value = "headStaffUid") String headStaffUid,
            @ApiParam(value = "总部员工名") @RequestParam(value = "headStaffName") String headStaffName,
            @ApiParam(value = "合同id") @RequestParam(value = "id") Long id
    ) {
        StoreContract data = storeContractService.getById(id);
        if (null == data)
            return R.fail("未查询到合同");

        List<StoreContractFile> fileList = storeContractFileService.listByContractId(id);
        if (CollectionUtils.isNotEmpty(fileList)) {
            // 合同文件添加token
            String ipAddr = IpUtil.getIpAddr(request);
            String token = ContractFileUtil.getToken(ipAddr);
            fileList.forEach(file -> {
                file.setUrl(file.getUrl() + token);
            });
            data.setFileList(fileList);
        }

        List<StoreContractGift> giftList = contractGiftService.listByContractId(id);
        if (CollectionUtils.isNotEmpty(giftList))
            data.setGiftList(giftList);

        return R.ok(data);
    }

    @Transactional(rollbackFor = DescribeException.class)
    @ApiOperation(value = "创建/更新合同信息")
    @PostMapping(value = "/newBean", produces = "application/json; charset=UTF-8")
    public R<Object> newBean(
            @ApiParam(value = "总部员工uid") @RequestParam(value = "headStaffUid") String headStaffUid,
            @ApiParam(value = "总部员工名") @RequestParam(value = "headStaffName") String headStaffName,
            @ApiParam(value = "id") @RequestParam(value = "id", required = false) Long id,
            @ApiParam(value = "门店uid") @RequestParam(value = "storeUid") String storeUid,
            @ApiParam(value = "合同编号") @RequestParam(value = "contractCode") String contractCode,
            @ApiParam(value = "合同描述") @RequestParam(value = "content", required = false) String content,
            @ApiParam(value = "合同开始日期") @RequestParam(value = "beginDate", required = false) String beginDate,
            @ApiParam(value = "合同结束日期") @RequestParam(value = "endDate", required = false) String endDate,
            @ApiParam(value = "合同金额") @RequestParam(value = "amount", required = false) Double amount,
            @ApiParam(value = "销售姓名") @RequestParam(value = "sellerName", required = false) String sellerName,
            @ApiParam(value = "签约日期") @RequestParam(value = "signDate", required = false) String signDate,
            @ApiParam(value = "是否签署 1.是 0.否") @RequestParam(value = "signStatus") Integer signStatus,
            @ApiParam(value = "保证金") @RequestParam(value = "deposit", required = false) Double deposit,
            @ApiParam(value = "保证金是否已退") @RequestParam(value = "depositRefundStatus", required = false) Integer depositRefundStatus,
            @ApiParam(value = "合同类型") @RequestParam(value = "contractType") Integer contractType,
            @ApiParam(value = "合同类型名称") @RequestParam(value = "contractTypeName") String contractTypeName,
            @ApiParam(value = "文件地址集合[{id:0,url:''}]") @RequestParam(value = "fileJson", required = false) String fileJson,
            @ApiParam(value = "赠品集合") @RequestBody(required = false) List<StoreContractGift> giftList
    ) throws Exception {
        if (StringUtils.isBlank(contractCode))
            return R.fail("未填写合同编号");
        if (signStatus == null)
            return R.fail("未选择签署状态");

        Stores stores = storesService.getByUid(storeUid);
        if (stores == null)
            return R.fail("未查询到门店");

        String corpUid = stores.getCorpUid();

        StoreContract data = null;
        if (null == id || id <= 0) {
            data = new StoreContract();
            data.setAddStaffUid(headStaffUid);
            data.setAddStaffName(headStaffName);
            data.setCorpUid(corpUid);
            data.setStoreUid(storeUid);
        } else {
            data = storeContractService.getById(id);
            if (null == data)
                return R.fail("未查询到合同");
            List<String> identifyList = adminRoleStaffService.identifyListByStaffUid(headStaffUid);
            boolean manager = AdminStaffRoleUtil.isSuperAdmin(identifyList);
            boolean leader = AdminStaffRoleUtil.isManager(identifyList);
            if (!manager && !leader) {
                if (TimeUtil.moreThanDay(data.getAddTime(), 180))
                    return R.fail("添加已超过半年，不能操作");
            }
        }
        data.setContractCode(contractCode);
        data.setContent(content);
        data.setSellerName(sellerName);
        data.setAmount(amount);
        data.setContractType(contractType);
        data.setContractTypeName(contractTypeName);
        data.setDeposit(deposit);
        if (deposit != null && deposit > 0)
            data.setDepositRefundStatus(depositRefundStatus);
        else
            data.setDepositRefundStatus(null);
        if (StringUtils.isNotBlank(beginDate))
            data.setBeginDate(DateUtil.parseDate(beginDate));
        if (StringUtils.isNotBlank(endDate))
            data.setEndDate(DateUtil.parseDate(endDate));
        if (StringUtils.isNotBlank(signDate))
            data.setSignDate(DateUtil.parseDate(signDate));
        data.setSignStatus(signStatus);
        data.setLastStaffUid(headStaffUid);
        data.setLastStaffName(headStaffName);
        storeContractMapper.insertOrUpdate(data, false);

        // 保存合同文件
        if (StringUtils.isNotBlank(fileJson)) {
            List<StoreContractFile> fileList = JSONArray.parseArray(fileJson, StoreContractFile.class);

            List<Long> ids = new ArrayList<>();
            for (StoreContractFile file : fileList) {
                if (file.getId() == null || file.getId() <= 0) {
                    file.setContractId(data.getId());
                    file.setCorpUid(corpUid);
                    file.setStoreUid(storeUid);
                    file.setAddStaffUid(headStaffUid);
                    file.setAddStaffName(headStaffName);
                } else {
                    ids.add(file.getId());
                }
            }

            // 先删除不保存的文件
            storeContractFileService.deleteByFileIdsNotIn(data.getId(), ids);
            storeContractFileService.saveOrUpdateBatch(fileList);
        } else {
            storeContractFileService.deleteByContractId(data.getId());
        }

        // 赠品
        if (CollectionUtils.isNotEmpty(giftList)) {
            List<Long> ids = new ArrayList<>();
            for (StoreContractGift gift : giftList) {
                if (gift.getId() == null || gift.getId() <= 0) {
                    gift.setContractId(data.getId());
                    gift.setCorpUid(corpUid);
                    gift.setStoreUid(storeUid);
                    gift.setAddStaffUid(headStaffUid);
                    gift.setAddStaffName(headStaffName);
                    gift.setStatus(0);
                } else {
                    ids.add(gift.getId());
                }
                gift.setLastStaffUid(headStaffUid);
                gift.setLastStaffName(headStaffName);
            }
            // 先删除不保存的赠品
            contractGiftService.deleteByIdsNotIn(data.getId(), ids);
            contractGiftService.saveOrUpdateBatch(giftList);
        } else {
            contractGiftService.deleteByContract(data.getId());
        }

        // 跟进记录
        if (id == null || id <= 0) {
            StoreFollowUtil.newSystemLog(
                    StoreFollowEnum.CONTRACT_ADD.getType(), "合同编号：" + contractCode, corpUid, storeUid,
                    headStaffUid, headStaffName
            );
        }
        return R.ok();
    }

    @ApiOperation(value = "更新签署状态")
    @PostMapping(value = "/updateSignStatus", produces = "application/json; charset=UTF-8")
    public R<Object> updateSignStatus(
            @ApiParam(value = "总部员工uid") @RequestParam(value = "headStaffUid") String headStaffUid,
            @ApiParam(value = "总部员工名") @RequestParam(value = "headStaffName") String headStaffName,
            @ApiParam(value = "合同id") @RequestParam(value = "id") Long id,
            @ApiParam(value = "是否签署 1.是 0.否") @RequestParam(value = "signStatus") Integer signStatus
    ) {
        StoreContract data = storeContractService.getById(id);
        if (data == null)
            return R.fail("未查询到合同");
        if (data.getSignStatus().equals(1)) {
            if (TimeUtil.moreThanDay(data.getSignDate(), 30)) {
                return R.fail("签署超过30天，不能操作");
            }
        }

        boolean b = storeContractService.updateSignStatus(id, signStatus);
        if (b && signStatus.equals(1)) {
            // 跟进记录
            StoreFollowUtil.newSystemLog(
                    StoreFollowEnum.CONTRACT_SING.getType(), "合同编号：" + data.getContractCode(),
                    data.getCorpUid(), data.getStoreUid(), headStaffUid, headStaffName
            );
        }
        return R.ok();
    }

    @ApiOperation(value = "删除合同")
    @PostMapping(value = "/deleteBean", produces = "application/json; charset=UTF-8")
    public R<Object> deleteBean(
            @ApiParam(value = "总部员工uid") @RequestParam(value = "headStaffUid") String headStaffUid,
            @ApiParam(value = "总部员工名") @RequestParam(value = "headStaffName") String headStaffName,
            @ApiParam(value = "合同id") @RequestParam(value = "id") Long id
    ) {
        StoreContract data = storeContractService.getById(id);
        if (data == null)
            return R.fail("未查询到合同");

        if (TimeUtil.moreThanDay(data.getAddTime(), 30))
            return R.fail("添加已超过30天，不能删除");

        boolean b = storeContractService.removeById(id);
        if (!b)
            return R.failDel();

        // 删除文件
        storeContractFileService.deleteByContractId(id);

        // 跟进记录
        StoreFollowUtil.newSystemLog(
                StoreFollowEnum.CONTRACT_DELETE.getType(), "合同编号：" + data.getContractCode(),
                data.getCorpUid(), data.getStoreUid(), headStaffUid, headStaffName
        );
        return R.ok();
    }

    @ApiOperation(value = "上传文件")
    @PostMapping(value = "/uploadFile", produces = "application/json; charset=UTF-8")
    public R<Object> uploadFile(
            HttpServletRequest request,
            @ApiParam(value = "总部员工uid") @RequestParam(value = "headStaffUid") String headStaffUid,
            @ApiParam(value = "总部员工名") @RequestParam(value = "headStaffName") String headStaffName,
            @ApiParam(value = "文件") @RequestPart(value = "file") MultipartFile file
    ) throws Exception {
        // 上传图片到服务器
        R<String> r = LocalFileUtil.uploadFile(LocalFileUtil.contractBaseDir, file);
        if (R.isError(r))
            return R.fail(r.getMsg());

        // 合同文件添加token
        String ipAddr = IpUtil.getIpAddr(request);
        String token = ContractFileUtil.getToken(ipAddr);
        return R.ok(r.getData() + token);
    }

    @ApiOperation(value = "设置赠品交付")
    @PostMapping(value = "/setGiftDone", produces = "application/json; charset=UTF-8")
    public R<Object> setGiftDone(
            @ApiParam(value = "总部员工uid") @RequestParam(value = "headStaffUid") String headStaffUid,
            @ApiParam(value = "总部员工名") @RequestParam(value = "headStaffName") String headStaffName,
            @ApiParam(value = "赠品id") @RequestParam(value = "giftId") Long giftId,
            @ApiParam(value = "交付状态 0.待交付 1.部分交付 2.交付完成") @RequestParam(value = "status") Integer status,
            @ApiParam(value = "部分交付备注") @RequestParam(value = "partRemark", required = false) String partRemark,
            @ApiParam(value = "完成交付备注") @RequestParam(value = "remark", required = false) String remark
    ) throws Exception {
        if (status == null)
            return R.fail("请选择交付状态");
        if (status.equals(0))
            return R.fail("交付状态错误");
        if (status.equals(1) && StringUtils.isBlank(partRemark))
            return R.fail("请填写部分交付的备注");

        StoreContractGift gift = contractGiftService.getById(giftId);
        if (gift == null)
            return R.fail("未查询到赠品");
        if (gift.getStatus().equals(2))
            return R.fail("已完成交付，不能操作");

        boolean b = contractGiftService.setGiftDone(giftId, status, partRemark, remark);
        if (!b)
            return R.fail("赠品交付失败");

        return R.ok();
    }

    @ApiOperation(value = "访问合同文件的权限")
    @GetMapping(value = "/verifyFile", produces = "application/json; charset=UTF-8")
    public void verifyFile(
            HttpServletRequest request,
            HttpServletResponse response,
            @ApiParam(value = "参数") @RequestParam(value = "path") String path,
            @ApiParam(value = "令牌") @RequestParam(value = "token") String token
    ) throws Exception {
        if (StringUtils.isBlank(path))
            throw new DescribeException("未传递文件路径");
        if (StringUtils.isBlank(token))
            throw new DescribeException("未传递token");

        String decryToken = ContractFileUtil.decryToken(token);
//        System.out.println("decryToken = " + decryToken);
        if (StringUtils.isBlank(decryToken))
            throw new DescribeException("token解密失败");
        String[] tokens = StringUtils.split(decryToken, ",");
        String expireStr = tokens[0];
        String ipAddr = tokens[1];
        if (StringUtils.isBlank(expireStr))
            throw new DescribeException("未获取到时间");
        if (StringUtils.isBlank(ipAddr))
            throw new DescribeException("未获取到ip");
        String ip = IpUtil.getIpAddr(request);
        if (!ip.equals(ipAddr))
            throw new DescribeException("ip地址不符合");
        Date expiryTime = DateUtil.parseDateFromStr(expireStr);
        if (expiryTime.getTime() < System.currentTimeMillis())
            throw new DescribeException("访问链接已过期");


        // 设置contentType
        if (path.contains(".png") || path.contains(".jpg") || path.contains(".jpeg")) {
            response.setContentType("image/png");
        } else if (path.contains(".pdf")) {
            response.setContentType("application/pdf");
        } else {
            throw new DescribeException("文件类型错误");
        }

        // lessonPdfFile/bds/pdf/1.pdf → bds/pdf/1.pdf
        String fileUrl = LocalFileUtil.contractBaseDir + path;
//        System.out.println("fileUrl = " + fileUrl);
        File file = new File(fileUrl);
        // 未找到文件返回默认pdf
        if (!file.exists()) {
            file = new File("/home/dingcloud/img/error.html");
            // 设置contentType
            response.setContentType("text/html");
            response.setCharacterEncoding("UTF-8");
        }

        // 将文件输出到页面
        ServletOutputStream out = null;
        try {
            FileInputStream inputStream = new FileInputStream(file);
            out = response.getOutputStream();
            int b = 0;
            byte[] buffer = new byte[1024];
            while ((b = inputStream.read(buffer)) != -1) {
                // 4.写到输出流(out)中
                out.write(buffer, 0, b);
            }
            inputStream.close();
            out.flush();
        } catch (IOException e) {
            e.printStackTrace();
        } finally {
            if (out != null) {
                try {
                    out.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
        }
    }
//    @ApiOperation(value = "验证文件访问权限")
//    @GetMapping(value = "/verifyFile", produces = "application/json; charset=UTF-8")
//    public R<Object> verifyFile(
//            @ApiParam(value = "加密uid") @RequestParam(value = "uid") String uid
//    ) throws Exception {
//        
//
//        String content = RC4Util.decry_RC4(uid, "dingding");
//        if (StringUtils.isNotBlank(content))
//            return R.fail("解密失败");
//
//        String[] split = content.split("-");
//        String staffUid = split[0];
//        HeadStaff headStaffObj = headStaffService.getByUid(staffUid);
//        if (headStaffObj == null)
//            return R.fail("员工不存在");
//        if (!headStaffObj.getEnabled().equals(1))
//            return R.fail("员工已被禁用");
//
//        String time = split[1];
//        if (StringUtils.isBlank(time))
//            return R.fail("时间戳不存在");
//        Date expiryTime = DateUtil.parseDate(time);
//        if (expiryTime.getTime() < System.currentTimeMillis())
//            return R.fail("访问已过期");
//
//
//        return R.ok();
//    }

}